使用捏合操纵器可以使用户在 Kanzi 应用程序中缩放和旋转节点。为了计算缩放和旋转节点的量,捏合手势持续跟踪设备屏幕上两个手指之间的位置和位置。
使用多击操纵器可以使用户在 Kanzi 应用程序中多击或多敲节点。您可在多击操纵器中设置轻敲次数和Kanzi 两次轻敲之间的最长时间,以将多次轻敲解释为多击手势。
这一步中首先使用捏合手势实现地图的缩放和旋转。然后使用多击操纵器实现地图位置、缩放水平和旋转角度的重置。
在 Android 设备上部署该教程应用程序,因为捏合手势需要多击支持。
这一节中,您将创建和使用捏合操纵器,在用户捏合地图时缩放和旋转地图。
要缩放和旋转地图:
PanZoomTap 类的私有部分定义捏合消息的处理程序:private:
...
//为 PinchManipulator::StartedMessage 消息定义处理程序,该消息来自
//具有可生成捏合消息的输入操纵器的 2D 节点。
//此处理程序可为捏合手势准备 2D 节点。
void onPinchStarted(PinchManipulator::StartedMessageArguments& messageArguments)
{
//从消息参数获得用户捏合的节点。
Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource());
//存储渲染变换 (Render Transformation) 属性缩放 (Scale) 属性字段的初始值。
SRTValue2D nodeTransform = mapNode->getRenderTransformation();
m_pinchInitialScaleFactor = nodeTransform.getScale().getX() - 1.0f;
//根据应用程序屏幕的大小计算最小比例值。
ScreenSharedPtr screen = getScreen();
m_minScale = max(getScreen()->getActualWidth() / mapNode->getActualWidth(), screen->getActualHeight() / mapNode->getActualHeight());
}
//为 PinchManipulator::MovedMessage 消息定义处理程序,该消息来自
//具有可生成捏合消息的输入操纵器的 2D 节点。
//这样可按捏合手势的量缩放和旋转 2D 节点。
void onPinchMoved(PinchManipulator::MovedMessageArguments& messageArguments)
{
//从消息参数获得用户捏合的节点。
Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource());
//从消息参数获取比例和旋转。
float scaleDelta = messageArguments.getScale();
float rotateDelta = messageArguments.getRotation();
//通过添加初始比例到捏合值计算比例。
//限制比例,使得地图不小于应用程序屏幕的大小。
float scale = max(m_minScale, scaleDelta + m_pinchInitialScaleFactor);
//获取 Map 节点的渲染变换 (Render Transformation) 属性。
SRTValue2D mapRenderSRT = mapNode->getRenderTransformation();
//应用旋转。
mapRenderSRT.rotate(rotateDelta);
//应用比例。
mapRenderSRT.setScale(Vector2(scale, scale));
//获取 Map 节点的世界变换。
//在该教程的下一步使用。
Matrix3x3 mapWorldTransform = mapNode->getWorldTransform();
SRTValue2D mapWorldSRT = *SRTValue2D::create(mapWorldTransform);
//应用新渲染变换到 Map 节点。
mapNode->setRenderTransformation(mapRenderSRT);
}
//为捏合手势的初始比例因子定义成员变量。
float m_pinchInitialScaleFactor;
//为最小比例值定义成员变量。
float m_minScale;
};PanZoomTap 类的公有部分开始处添加构造函数,并为该捏合手势设置初始比例因子:public:
PanZoomTap() :
m_pinchInitialScaleFactor(0.0f)
{
}
...onProjectLoaded() 函数中创建 PinchManipulator 操纵器并订阅 Map 节点的消息: virtual void onProjectLoaded() KZ_OVERRIDE
{
...
//创建生成捏合消息的输入操纵器。
PinchManipulatorSharedPtr pinchManipulator = PinchManipulator::create(domain);
//添加输入操纵器到 Map 节点。
mapNode->addInputManipulator(pinchManipulator);
//订阅 Map 节点的 PinchManipulator::StartedMessage 消息。
// PinchManipulator 在用户在 Map 节点按下两根手指时生成此消息。
mapNode->addMessageHandler(PinchManipulator::StartedMessage, bind(&PanZoomTap::onPinchStarted, this, placeholders::_1));
//订阅 Map 节点的 PinchManipulator::MovedMessage 消息。
//PinchManipulator 在超出比例或旋转阈值时生成此消息,
//并在被跟踪触摸在更新之间移动时生成此消息。
mapNode->addMessageHandler(PinchManipulator::MovedMessage, bind(&PanZoomTap::onPinchMoved, this, placeholders::_1));
}
在您的 Android 设备上使用捏合手势缩放和旋转地图。
地图围绕其中心点旋转,因为 Map 节点的原点被设置为中心。
在本节中,您将使用多击操纵器在用户双敲地图时重置地图的位置、缩放水平和旋转角度。
要重置位置、缩放水平和旋转:
PanZoomTap 类的私有部分定义多击消息的处理程序:private:
...
//为 MultiClickManipulator::MultiClickMessage 消息定义处理程序,该消息来自
//具有可在用户双敲节点时生成多击消息的输入操纵器的节点。
void onNodeDoubleTapped(MultiClickManipulator::MultiClickMessageArguments& messageArguments)
{
//从消息参数获取用户双敲的节点。
Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource());
//移除该节点的渲染变换 (Render Transformation) 属性。
//这样即可重置 Map 节点的位置、缩放水平和旋转角度。
mapNode->removeLocalValue(Node2D::RenderTransformationProperty);
}
...
};onProjectLoaded() 函数中创建并配置 MultiClickManipulator 操纵器并订阅 Map 节点的消息: virtual void onProjectLoaded() KZ_OVERRIDE
{
...
//创建生成多击消息的输入操纵器。
MultiClickManipulatorSharedPtr multiClickManipulator = MultiClickManipulator::create(domain);
//添加输入操纵器到Map 节点。
mapNode->addInputManipulator(multiClickManipulator);
//默认情况下,输入操纵器将两次轻敲识别为双敲手势。
//要使用不同次数的轻敲,使用 MultiClickManipulator::setExpectedClicks 函数。
//例如,将输入操纵器设置为将三次轻敲识别为多击手势,将 3 传递给该函数。
// multiClickManipulator->setExpectedClicks(3);
//将双敲超时设置为 300 ms。如果两次轻敲之间的时间未超出该值,
//输入操纵器将这些轻敲识别为双敲手势。默认超时为 250 ms。
multiClickManipulator->setTimeout(chrono::milliseconds(300));
//订阅Map 节点的 MultiClickManipulator::MultiClickMessage 消息。
// MultiClickManipulator 操纵器在用户双敲节点时生成此消息。
mapNode->addMessageHandler(MultiClickManipulator::MultiClickMessage, bind(&PanZoomTap::onNodeDoubleTapped, this, placeholders::_1));
}要详细了解捏合操纵器,请参阅使用捏合操纵器。
要详细了解多击操纵器,请参阅使用多击操纵器。
要详细了解部署 Kanzi 应用程序到 Android,请参阅部署 Kanzi 应用程序到 Android。